﻿using System.ComponentModel;
using System.Diagnostics;

namespace Neitzel.Irc.Client
{
    /// <summary>
    /// User in a Channel
    /// </summary>
    public class ChannelUser : INotifyPropertyChanged
    {
        #region Fields

        /// <summary>
        /// Log4net logger to use inside this class.
        /// </summary>
        private static readonly TraceSource Logger = new TraceSource(IrcConstants.TraceSourceName);
        
        #endregion 

        #region Constants

        /// <summary>
        /// Flag that makes user to a channel operator.
        /// </summary>
        public const char OperatorAttribute = 'o';

        /// <summary>
        /// Flag that gives user voice rights in moderated channel.
        /// </summary>
        public const char VoiceAttribute = 'v';

        #endregion

        #region Lifetime

        /// <summary>
        /// Initializes a new instance of the ChannelUser class.
        /// </summary>
        /// <param name="name">Name of User</param>
        public ChannelUser(string name)
        {
            _name = name;
            _attributes = new UniversalAttributes();
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the name of the user.
        /// </summary>
        public string Name
        {
            get { return _name; }
            set { _name = value; OnPropertyChanged(this, new PropertyChangedEventArgs("Name")); }
        }
        private string _name;

        /// <summary>
        /// Gets or sets the flags of the user.
        /// </summary>
        public UniversalAttributes Attributes
        {
            get { return _attributes; }
            private set 
            { 
                _attributes = value; 
                OnPropertyChanged(this, new PropertyChangedEventArgs(nameof(Attributes)));
                _attributes.PropertyChanged += (sender, e) => OnPropertyChanged(this, new PropertyChangedEventArgs(nameof(Attributes)));
            }
        }
        private UniversalAttributes _attributes;

        /// <summary>
        /// Gets the display name of the user.
        /// </summary>
        /// <remarks>
        /// The DisplayName also includes a @ if user is an operator in channel or a + if user has voice.
        /// </remarks>
        public virtual string DisplayName
        {
            get
            {
                var prefix = string.Empty;

                // prefix voice with +
                if (HasVoice())
                    prefix = "+";

                // prefix operator with @ (overrides voice if user has both!)
                if (IsOperator())
                    prefix = "@";

                // return prefix with name
                return prefix + Name;
            }
        }
        #endregion

        #region Public Methods

        /// <summary>
        /// Is user a Channel Operator
        /// </summary>
        /// <returns>true if user is channel operator else false.</returns>
        public bool IsOperator()
        {
            return Attributes.IsSet(OperatorAttribute);
        }

        /// <summary>
        /// Does the User has voice Flag set.
        /// </summary>
        /// <returns>True if user has voice flag set.</returns>
        public bool HasVoice()
        {
            return Attributes.IsSet(VoiceAttribute);
        }

        #endregion

        #region INotifyPropertyChanged parts

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            // prevent racing conditions
            var handler = PropertyChanged;

            // trigger event
            handler?.Invoke(sender, e);
        }

        #endregion
    }
}
